#include "edaTS.h"

edaTS::edaTS()
  : move(NULL),
    continueCriteria(NULL),
    moveExpl(NULL)
{
}

edaTS::edaTS( edaMove *_move,
    edaMoveGen *_moveNext,
    edaTabuList *_tabuList,
    edaAspirCrit *_aspirCrit,
    edaContinue *_continueCriteria)
{
  move = _move->clone();
  moveExpl = new edaTSMoveExpl(_moveNext, _tabuList, _aspirCrit);
  continueCriteria = _continueCriteria->clone();
}

edaTS::edaTS(edaMove *_move,
    edaTSMoveExpl *_moveExpl,
    edaContinue *_continueCriteria)
{
  move = _move->clone();
  moveExpl = (edaTSMoveExpl *)_moveExpl->clone();
  continueCriteria = _continueCriteria->clone();
}

edaTS::~edaTS()
{
  clean();
}

bool edaTS::search(edaSolution &sol)
{
  edaSolution *bestSol = sol.clone();
  edaSolution *newSol = sol.clone();

  continueCriteria->init();

  do
  {
    *newSol = sol;

    moveExpl->explore(move, sol, *newSol);

    if (newSol->fullEvaluate() > sol.fullEvaluate())
    {
      *bestSol = *newSol;
    }

    sol = *newSol;

    printDebug(5, "new fitness: " << sol.fullEvaluate() );
  }
  while (continueCriteria->check(sol));
  
  sol = *bestSol;

  delete newSol;
  delete bestSol;
  return true;
}

void edaTS::Serialize(edaBuffer &buf, bool pack)
{
  if (pack)
  {
    move->doSerialize(buf, pack);
    continueCriteria->doSerialize(buf, pack);
    moveExpl->doSerialize(buf, pack);
  }
  else
  {
    // Clean old data
    clean();

    move = (edaMove*)classGenerateFromBuffer(buf);
    continueCriteria = (edaContinue*)classGenerateFromBuffer(buf);
    moveExpl = (edaTSMoveExpl*)classGenerateFromBuffer(buf);
  }
}

void edaTS::clean()
{
  if (move != NULL)
  {
    delete move;
    move = NULL;
  }
  if (continueCriteria != NULL)
  {
    delete continueCriteria;
    continueCriteria = NULL;
  }
  if (moveExpl != NULL)
  {
    delete moveExpl;
    moveExpl = NULL;
  }
}
